Tdbs 1.2-16/SAMPLES/SFILE.PRG

6.5 KB aa0e2d832917998c…
*
* Simple File Search Utility
* Revision 1.00
* Written by Alan D. Bryant
* for eSoft, Inc.
*
****************************************************************************
* This program source is included with your TDBS to illustrate techniques. *
* You may use any or all of the source or techniques illustrated in this   *
* program in any fashion you wish.  There are no fees or restrictions      *
* imposed on the use of this code by eSoft, Inc.                           *
****************************************************************************
*
* PURPOSE:  This program implements a simple text search and
* download utility.  The program is "pointed" to a particular file mask
* via Opt Data, then a user can perform a single key keyword search on
* all the files which are included in that mask.
*
* Files which match are stored in a database, and can then be downloaded
* after the search is completed.  If too many files matched, they can
* be downloaded in groups.
*
* Batch protocols must be used the way the program is currently structured,
* and the download function is called in such a way as to prevent use of
* non-batch protocols.
*
* CONCEPTS ILLUSTRATED:  Several concepts are outlined here, including
* the use of the file I/O system, building temporary databases, use of
* the file I/O system's text search capability, multi-file accesses, and
* much more.  This program could serve as the engine for
*
* If you have the regular version of TDBS (with the compiler), there are
* many changes and enhancements which could be made to this program.
* These include the ability to use non-batch protocols or to read the files
* online; multiple key searches; a better user interface; etc.  Think about
* the possibilities!
*
*



* initial stuff

set exclusive off
clear

* parse the opt data comments out

offset = at(chr(38)+chr(38), optdata())

* the opt data line isn't formatted properly

if offset = 0
    ? "SFILE: Opt data command line improperly configured."
    key = inkey(2)
    quit
endif

* if there's a space included, note that so it can be ignored

if substr(optdata(), offset + 2, 1) = " "
    offset = offset + 1
endif

* get the file mask out of the Opt Data, and then get out just the
* root so it can be used later on
* the "mask" is used for the findfirst function
* the "root" is the mask with the filename reference removed
* e.g.,   C:\TDBS\APPS\SFILE /Q && D:\TEXT\SFILE\TECH*.TXT    Opt Data
*                                  D:\TEXT\SFILE\TEXT*.TXT    Mask
*                                  D:\TEXT\SFILE\             Root

mask = substr(optdata(), offset + 2)
backoff = rat("\", mask)
if backoff # 0
    root = substr(mask, 1, backoff)
else
    root = ""
endif

* find the first match occurrance of the mask

fname = findfirst(intern, mask)

* if findfirst() returns a null string, nothing was found which matches

if empty(fname)
    ? "SFILE: No files match the search mask in Opt Data."
    key = inkey(2)
    quit
else
    * we're here if a match was found; build a temporary database

    create newstruc
    use newstruc
    append blank
    replace field_name with "MATCH", field_type with "C", field_len with 12
    use
    ourname = "SFILE"+uline()
    create &ourname from newstruc
    erase newstruc.dbf
    use &ourname

    * prompt for a search key and confirm

    accept "Enter a search key? " to skey
    ? ""
    ? "Initiate a search for "+chr(34)+skey+chr(34)+"? (Y/N) "
    key = inkey(0)
    sel = upper(chr(key))
    if sel = "N"
        quit
    endif
    ? ""
    ? "Initiating search.  This could take a few moments..."

    * open the file for the first found occurrance

    do while .t.
        fopen handle (root+fname) 10 2048
        if handle = -1
            ? "SFILE: File open error"
            ? "SFILE: "+root+fname+" - "+message(ferror())
            wait
            quit
        endif

        * issue an flfind to search for the string in this file

        ? "Searching "+fname+"..."
        flfind handle matchoff rtrim(skey) 1
        fclose
        if matchoff = -1
            ? "SFILE: File search error"
            ? "SFILE: "+root+fname+" - "+message(ferror())
            wait
            quit
        endif

        * if the search key was found in the file, append its name to
        * the temp database for later

        if matchoff # 0
            append blank
            replace MATCH with fname
        endif

        * find the next occurrance of the mask; if nothing is found,
        * exit the loop

        fname = findnext(intern)
        if empty(fname)
            exit
        endif
    enddo

    * we're done with the searching; if the database has no records in it
    * then no matches were found; report and quit; otherwise, start downloading
    * of files

    if reccount() = 0
        ? "No matches were found for your search key."
        wait
        quit
    else

        * toolong is used to keep track of whether or not there are too
        * many matching files by getting the size of the opt data when
        * built

        toolong = 0

        * prompt whether to download the files

        ? "A total of "+ltrim(str(reccount()))+" files matched your criteria."
        ? "Would you like to download the matched files? (Y/N)"
        key = inkey(0)
        sel = upper(chr(key))
        if sel = "N"
            quit
        endif

        * start the process of downloading by building the opt data first
        * the build an opt data and allow download to begin

        goto top
        do while .t.
            filelist = ""
            do while .not. eof()
                filelist = filelist+rtrim(match)+" "
                skip
                pointer = recno()
                if len(filelist) > 80
                    if toolong = 0
                        ? "The list of files is long.  You'll have to download them in batches."
                        wait
                        toolong = 1
                    endif
                    exit
                endif
            enddo
            command = root+" /P:6789AB/NL/I:"+chr(34)+"D "+filelist+chr(34)
            if toolong = 0
                wait
            endif
            dotbbs type 34 optdata command
            use &ourname
            if pointer < reccount()
                goto pointer
            else
                exit
            endif
        enddo
    endif
endif